1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*

THIS IS DISABLED FOR NOW, BECAUSE WE DON'T REALLY NEED IT SO FAR.

use crate::app::event::UserAction;
use crate::app::state::{Consumed, DynSessionState, SessionState};
use crate::app::{AeonError, DynError};
use std::collections::HashMap;

/// A group of several dynamic state objects accessible using path segments.
///
/// It is generally assumed that the managed state objects are created statically at the
/// same time as [MapState], because we cannot create/remove states dynamically from this
/// map using just events (although you could in theory do it internally from Rust).
#[derive(Default)]
pub struct MapState {
    pub state: HashMap<String, DynSessionState>,
}

impl<'a> FromIterator<(&'a str, DynSessionState)> for MapState {
    fn from_iter<T: IntoIterator<Item = (&'a str, DynSessionState)>>(iter: T) -> Self {
        let map = HashMap::from_iter(iter.into_iter().map(|(k, v)| (k.to_string(), v)));
        MapState { state: map }
    }
}

impl SessionState for MapState {
    fn consume_event(&mut self, path: &[&str], action: &UserAction) -> Result<Consumed, DynError> {
        let Some(prefix) = path.first() else {
            return AeonError::throw("State map cannot consume an empty path.");
        };
        let Some(sub_state) = self.state.get_mut(*prefix) else {
            let msg = format!("Unknown path segment `{}`.", prefix);
            return AeonError::throw(msg);
        };
        sub_state.consume_event(&path[1..], action)
    }
}

#[cfg(test)]
mod tests {
    use crate::app::event::{Event, UserAction};
    use crate::app::state::_state_map::MapState;
    use crate::app::state::{AtomicState, Consumed, DynSessionState, SessionState};

    #[test]
    fn test_map_state() {
        let inner: Vec<(&str, DynSessionState)> = vec![
            ("state_1", Box::new(AtomicState::from(5i32))),
            ("state_2", Box::new(AtomicState::from("test".to_string()))),
            ("state_3", Box::new(AtomicState::from(123u64))),
        ];
        let mut state_map = MapState::from_iter(inner.into_iter());

        let event_3: UserAction = Event::build(&["state_1"], Some("3")).into();
        let event_str: UserAction = Event::build(&["state_2"], Some("test")).into();

        let result = state_map.consume_event(&["state_1"], &event_3).unwrap();
        assert!(matches!(result, Consumed::Reversible(..)));
        let result = state_map.consume_event(&["state_2"], &event_str).unwrap();
        assert!(matches!(result, Consumed::NoChange));

        let result = state_map.consume_event(&[], &event_3).unwrap_err();
        assert_eq!(
            "State map cannot consume an empty path.",
            format!("{}", result)
        );

        let result = state_map.consume_event(&["state_4"], &event_3).unwrap_err();
        assert_eq!("Unknown path segment `state_4`.", format!("{}", result));
    }
}
*/